package com.cman777.springc.web.util;

import com.cman777.springc.common.bean.exception.BusinessException;
import com.cman777.springc.common.constants.ContentTypeConstants;
import com.cman777.springc.common.helper.JsonHelper;
import com.cman777.springc.common.helper.MapUtil;
import com.cman777.springc.common.helper.ValidateUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.*;

/**
 * @author chenzhicong
 * @time 2020/12/2 13:45
 */
@Log4j2
@Component
public class RestTemplateUtil {
    private static final RestTemplate REST_TEMPLATE = new RestTemplate();

    static {
        List<HttpMessageConverter<?>> converterList = REST_TEMPLATE.getMessageConverters();
        //重新设置StringHttpMessageConverter字符集为UTF-8，解决中文乱码问题
        //重新设置MappingJackson2HttpMessageConverter的objectMapper为统一mapper
        HttpMessageConverter<?> converterTarget = null;
        Iterator<HttpMessageConverter<?>> httpMessageConverterIterator = converterList.iterator();
        while (httpMessageConverterIterator.hasNext()) {
            HttpMessageConverter<?> item = httpMessageConverterIterator.next();
            if (StringHttpMessageConverter.class == item.getClass()) {
                ((StringHttpMessageConverter) item).setDefaultCharset(Charset.defaultCharset());
            }
            if (MappingJackson2HttpMessageConverter.class == item.getClass()) {
                ((MappingJackson2HttpMessageConverter) item).setObjectMapper(JsonHelper.getMvcObjectMapper());
            }
        }
    }

    public static RestTemplate getRestTemplate() {
        return REST_TEMPLATE;
    }

    public static <T, E> T doHttp4Body(String url, HttpMethod httpMethod,
                                       Map<String, String> headersMap, E body, Class<T> tClass) {
        return doHttp(url, httpMethod, headersMap, body, tClass).getBody();
    }

    public static <E> JsonNode doHttp4JsonBody(String url, HttpMethod httpMethod,
                                               Map<String, String> headersMap, E body) {
        try {
            return JsonHelper.getMvcObjectMapper().readTree(doHttp(url, httpMethod, headersMap, body, String.class).getBody());
        } catch (JsonProcessingException e) {
            throw new BusinessException("json转换错误");
        }
    }

    public static <E> String doHttp4StrBody(String url, HttpMethod httpMethod,
                                            Map<String, String> headersMap, E body) {
        return doHttp(url, httpMethod, headersMap, body, String.class).getBody();
    }


    public static <T, E> ResponseEntity<T> doHttp(String url, HttpMethod httpMethod,
                                                  Map<String, String> headersMap, E param, Class<T> tClass) {
        /**
         * 如果是get请求，把param转换为map用uri带参
         */
        HttpEntity<Object> httpEntity = null;
        if (HttpMethod.GET.equals(httpMethod)) {
            Map<String, Object> paramsMap = null;
            if (param!=null && !Map.class.isAssignableFrom(param.getClass())) {
                paramsMap = MapUtil.objectToMap(param);
            } else {
                paramsMap = (Map<String, Object>) param;
            }
            url = UrlUtil.packageUriAndParam(url, paramsMap);
            httpEntity = new HttpEntityBuilder().headers(headersMap).build();
        } else {
            httpEntity = new HttpEntityBuilder().body(param).headers(headersMap).defaultContentType(ContentTypeConstants.CONTENT_TYPE_APPLICATION_JSON_UTF8).build();
        }
        ResponseEntity<T> responseEntity = REST_TEMPLATE.exchange(url, httpMethod, httpEntity, tClass);
        return responseEntity;

    }

    public static class HttpEntityBuilder {
        private Map<String, String> headers = new HashMap<>();
        private Object body;
        private String defaultContentType;

        public HttpEntityBuilder headers(Map<String, String> headers) {
            if(!CollectionUtils.isEmpty(headers)){
                this.headers.putAll(headers);
            }
            return this;
        }

        public HttpEntityBuilder body(Object body) {
            this.body = body;
            return this;
        }

        public HttpEntityBuilder  defaultContentType(String defaultContentType) {
            this.defaultContentType = defaultContentType;
            return this;
        }


        public HttpEntity build() {
            if (!headers.containsKey("Content-Type") && !StringUtils.isEmpty(defaultContentType)) {
                headers.put("Content-Type", defaultContentType);
            }
            /*if(headers.get("Content-Type").contains(ContentTypeConstants.CONTENT_TYPE_APPLICATION_JSON)){
                 body =  JsonHelper.toJsonStringQuietly(body);

            }*/
            HttpHeaders httpHeaders = new HttpHeaders();
            headers.forEach((k, v) -> {
                httpHeaders.add(k, v);
            });
            return new HttpEntity(body, httpHeaders);
        }
    }

}
